package com.linck.port.controller;


import com.linck.port.constant.Constans;
import com.linck.port.constant.ExpireTypeEnum;
import com.linck.port.util.FileUtil;
import com.linck.port.util.RedisUtil;
import com.linck.port.util.ResultJson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Objects;
import java.util.UUID;

/**
 * @program: AirPort
 * @description
 * @author: Linck
 * @create: 2020-06-10 20:59
 **/
@Api("主功能api，上传，下载")
@Controller
public class MainController {

    private static final Logger logger = LoggerFactory.getLogger(MainController.class);



    @Autowired
    private RedisUtil redisUtil;

    /**
     * @author Linck
     * @description 进入主页
     * @return
     */
    @ApiOperation(value = "进入主页")
    @GetMapping(value = {"/","/index"})
    public String index(){
        return "index.html";
    }


    /**
     * @author Linck
     * @description 上传文件
     * @param file-上传的文件大小小于200MB
     * @param expireType-最大保存时间 1-一星期 2-一天 3-一小时
     * @return
     */
    @ApiOperation(value = "上传文件，上传的文件大小小于200MB")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "上传的文件"),
            @ApiImplicitParam(name = "expireType", value = "expireType-最大保存时间 1-一星期 2-一天 3-一小时"),
            @ApiImplicitParam(name = "downloadCount", value = "最大下载次数范围[1,10]")
    })
    @ResponseBody
    @PostMapping("uploadFile")
    public ResultJson uploadFile(@RequestParam("file") MultipartFile file, Integer expireType, Integer downloadCount) throws IOException {
        //验证文件
        if(Objects.isNull(file) || file.isEmpty()){
            return ResultJson.error(null, "上传文件为空");
        }
        if(expireType == null || downloadCount == null){
            return ResultJson.error(null, "请选择保存时间和下载次数");
        }

        //磁盘剩余空间验证
        File root = new File("/");
        if (root.exists()) {
            long total = root.getTotalSpace();
            long usableSpace = root.getUsableSpace();
            logger.info("当前磁盘："+root.getAbsolutePath()+" 剩余空间大小："+usableSpace/(1024*1024)+"MB");
            if(usableSpace < 1024 * 1024){
                return ResultJson.error(null, "磁盘可用空间小于1GB,暂停服务");
            }
        }else {
            return ResultJson.error(null, "磁盘错误，暂停服务");
        }

        //判断key有效时间,默认一天
        int expire = ExpireTypeEnum.ONEDAY.getValue();
        if(ExpireTypeEnum.ONEMONTH.getType() == expireType){
            expire = ExpireTypeEnum.ONEMONTH.getValue();
        }else if(ExpireTypeEnum.ONEHOUR.getType() == expire){
            expire = ExpireTypeEnum.ONEHOUR.getValue();
        }

        //判断下载次数，默认允许下载一次
        int count = 1;
        if(downloadCount != null && downloadCount > 0 && downloadCount < 11){
            count = downloadCount;
        }

        //上传文件名
        String fileName = file.getOriginalFilename();
        logger.info("上传文件名："+fileName);

        //生成portid直到不重复为止
        String portId = UUID.randomUUID().toString().replaceAll("-","").substring(16);
        while (redisUtil.hasKey("port:"+portId)){
            portId = UUID.randomUUID().toString().replaceAll("-","").substring(16);
        }

        //文件上传路径
        File filePath = new File("/PortFile/"+portId+"/"+fileName);
        logger.info("文件上传路径："+filePath.getAbsolutePath());
        //创建文件路径
        if(!filePath.getParentFile().exists()){
            filePath.getParentFile().mkdirs();
        }
        File file1 = new File(filePath.getAbsolutePath());
        file.transferTo(file1);

        //保存key
        boolean success = redisUtil.set(Constans.PORT_PREFIX + portId, count, expire);

        if(success){
            return ResultJson.success(portId, "文件上传成功 最大保存时间："+expire/3600+"小时 最多下载次数："+count);
        }else{
            return ResultJson.error(null, "文件上传失败");
        }
    }
    /**
     * @author Linck
     * @description 验证下载文件
     * @param portId
     */
    @ApiOperation(value = "验证下载文件", notes = "portId")
    @ResponseBody
    @PostMapping("/downloadFile")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "portId", value = "下载文件的密钥，用户输入"),
    })
    public ResultJson downloadFile(String portId){
        //数据校验
        if(portId == null || portId.trim().trim().equals("")){
            return ResultJson.error(null, "无效的下载码");
        }
        //去除可能输入的多余空格
        portId = portId.trim();
        if(!redisUtil.hasKey(Constans.PORT_PREFIX+portId)){
            return ResultJson.error(null, "没有发现对应的文件");
        }
        Integer downloadCount = (Integer) redisUtil.get(Constans.PORT_PREFIX + portId);
        if(downloadCount == null){
            return ResultJson.error(null, "没有发现对应的文件");
        }
        //代取文件文件夹
        File filePath = new File("/PortFile/"+portId+"/");
        File[] tempList = filePath.listFiles();

        if(tempList.length == 0){
            return ResultJson.error(null, "文件夹下文件数量为0");
        }
        return ResultJson.success(null, "开始下载，文件剩余下载次数：" + (downloadCount-1));
    }
    @ApiOperation(value = "验证下载文件", notes = "portId")
    @ResponseBody
    @GetMapping("/downloadFile")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "portId", value = "下载文件的密钥，用户输入"),
    })
    public void downloadFile(HttpServletResponse response, String portId){
        Integer downloadCount = (Integer) redisUtil.get(Constans.PORT_PREFIX + portId);
        if(downloadCount == null){
            return;
        }
        //代取文件文件夹
        File filePath = new File("/PortFile/"+portId+"/");
        File[] tempList = filePath.listFiles();

        if(tempList.length == 0){
            return;
        }
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        byte[] buffer = new byte[1024];
        for (File file:tempList){
            if(file.exists()){
                //文件输入流
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                //输出流
                OutputStream os = null;
                try {
                    response.setHeader("Content-Disposition", "attachment;fileName=" +   java.net.URLEncoder.encode(file.getName(),"UTF-8"));
                    //输出流
                    os = response.getOutputStream();
                    //文件输入流
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    try {
                        os.close();
                        fis.close();
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                //可下载次数减一
                if(downloadCount==1){
                    downloadCount--;
                    //删除文件
                    FileUtil.deleteFile(filePath);
                    //删除key
                    redisUtil.del(Constans.PORT_PREFIX + portId);
                    logger.info("下载成功，文件不再可下载");
                }else{
                    downloadCount--;
                    redisUtil.set(Constans.PORT_PREFIX + portId, downloadCount);
                }

            }
        }
        logger.info("下载成功，剩余下载次数："+downloadCount);
    }
}
